package main

import (
	"encoding/json"
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"strconv"
	"time"
)

// User 用户结构体
type User struct {
	ID       int    `json:"id"`
	Name     string `json:"name"`
	Email    string `json:"email"`
	Age      int    `json:"age"`
	CreateAt string `json:"create_at"`
}

// Response 响应结构体
type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data"`
}

// 模拟数据库
var users = []User{
	{ID: 1, Name: "张三", Email: "zhangsan@example.com", Age: 25, CreateAt: "2024-01-01"},
	{ID: 2, Name: "李四", Email: "lisi@example.com", Age: 30, CreateAt: "2024-01-02"},
}

// 获取所有用户
func getUsers(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	response := Response{
		Code:    200,
		Message: "获取用户列表成功",
		Data:    users,
	}

	json.NewEncoder(w).Encode(response)
}

// 根据ID获取用户
func getUserByID(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	// 获取URL中的ID参数,返回一个 map[string]string 类型的变量，包含URL中的所有参数
	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		response := Response{
			Code:    400,
			Message: "无效的用户ID",
			Data:    nil,
		}
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(response)
		return
	}

	for _, user := range users {
		if user.ID == id {
			response := Response{
				Code:    200,
				Message: "获取用户成功",
				Data:    user,
			}
			json.NewEncoder(w).Encode(response)
			return
		}
	}

	response := Response{
		Code:    404,
		Message: "用户不存在",
		Data:    nil,
	}
	w.WriteHeader(http.StatusNotFound)
	json.NewEncoder(w).Encode(response)
}

// 创建新用户
func createUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	var newUser User
	err := json.NewDecoder(r.Body).Decode(&newUser)
	if err != nil {
		response := Response{
			Code:    400,
			Message: "请求体格式错误",
			Data:    nil,
		}
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(response)
		return
	}

	// 生成新ID
	newUser.ID = len(users) + 1
	newUser.CreateAt = time.Now().Format("2006-01-02")

	users = append(users, newUser)

	response := Response{
		Code:    201,
		Message: "用户创建成功",
		Data:    newUser,
	}
	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(response)
}

// 更新用户
func updateUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		response := Response{
			Code:    400,
			Message: "无效的用户ID",
			Data:    nil,
		}
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(response)
		return
	}

	var updateUser User
	err = json.NewDecoder(r.Body).Decode(&updateUser)
	if err != nil {
		response := Response{
			Code:    400,
			Message: "请求体格式错误",
			Data:    nil,
		}
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(response)
		return
	}

	for i, user := range users {
		if user.ID == id {
			updateUser.ID = id
			updateUser.CreateAt = user.CreateAt
			users[i] = updateUser

			response := Response{
				Code:    200,
				Message: "用户更新成功",
				Data:    updateUser,
			}
			json.NewEncoder(w).Encode(response)
			return
		}
	}

	response := Response{
		Code:    404,
		Message: "用户不存在",
		Data:    nil,
	}
	w.WriteHeader(http.StatusNotFound)
	json.NewEncoder(w).Encode(response)
}

// 删除用户
func deleteUser(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	vars := mux.Vars(r)
	id, err := strconv.Atoi(vars["id"])
	if err != nil {
		response := Response{
			Code:    400,
			Message: "无效的用户ID",
			Data:    nil,
		}
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(response)
		return
	}

	for i, user := range users {
		if user.ID == id {
			users = append(users[:i], users[i+1:]...)

			response := Response{
				Code:    200,
				Message: "用户删除成功",
				Data:    nil,
			}
			json.NewEncoder(w).Encode(response)
			return
		}
	}

	response := Response{
		Code:    404,
		Message: "用户不存在",
		Data:    nil,
	}
	w.WriteHeader(http.StatusNotFound)
	json.NewEncoder(w).Encode(response)
}

// 健康检查接口
func healthCheck(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	response := Response{
		Code:    200,
		Message: "服务运行正常",
		Data: map[string]interface{}{
			"timestamp": time.Now().Format("2006-01-02 15:04:05"),
			"status":    "healthy",
		},
	}

	json.NewEncoder(w).Encode(response)
}

// 中间件：日志记录
func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		next.ServeHTTP(w, r)
	})
}

// 中间件：CORS支持
func corsMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Access-Control-Allow-Origin", "*")
		w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

		if r.Method == "OPTIONS" {
			w.WriteHeader(http.StatusOK)
			return
		}

		next.ServeHTTP(w, r)
	})
}

func main() {
	// 创建路由器
	router := mux.NewRouter()

	// 添加中间件
	router.Use(loggingMiddleware)
	router.Use(corsMiddleware)

	// 定义路由
	router.HandleFunc("/health", healthCheck).Methods("GET")
	router.HandleFunc("/api/users", getUsers).Methods("GET")
	router.HandleFunc("/api/users", createUser).Methods("POST")
	router.HandleFunc("/api/users/{id}", getUserByID).Methods("GET")
	router.HandleFunc("/api/users/{id}", updateUser).Methods("PUT")
	router.HandleFunc("/api/users/{id}", deleteUser).Methods("DELETE")

	// 启动服务器
	port := ":8080"
	fmt.Printf("HTTP服务器启动在端口 %s\n", port)
	fmt.Println("可用的接口:")
	fmt.Println("  GET  /health           - 健康检查")
	fmt.Println("  GET  /api/users        - 获取所有用户")
	fmt.Println("  POST /api/users        - 创建新用户")
	fmt.Println("  GET  /api/users/{id}   - 获取指定用户")
	fmt.Println("  PUT  /api/users/{id}   - 更新指定用户")
	fmt.Println("  DELETE /api/users/{id} - 删除指定用户")

	log.Fatal(http.ListenAndServe(port, router))
}
